package org.jsola.hr.service.impl;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.jsola.core.Page;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.IAttendPlanDAO;
import org.jsola.hr.dto.AttendPlanAddDTO;
import org.jsola.hr.dto.AttendPlanUpdateDTO;
import org.jsola.hr.entity.*;
import org.jsola.hr.query.*;
import org.jsola.hr.service.*;
import org.jsola.hr.vo.AttendPlanListVO;
import org.jsola.hr.vo.AttendPlanVO;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author zhr
 */
@Slf4j
@Service("hrAttendPlanServiceImpl")
public class AttendPlanServiceImpl implements IAttendPlanService {

    @Autowired
    private IAttendPlanDAO attendPlanDAO;
    @Autowired
    private IAttendPunchStaffService attendPunchStaffService;
    @Autowired
    private IEmpDepService empDepService;
    @Autowired
    private IAttendPunchDeptService attendPunchDeptService;
    @Autowired
    private IAttendShiftStaffScheduleService attendShiftStaffScheduleService;

    /**
     * 新增考勤方案
     *
     * @param attendPlanAddDTO 新增考勤方案DTO
     * @param tokenUser 当前用户
     * @return
     */
    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public AttendPlanVO save(AttendPlanAddDTO attendPlanAddDTO, TokenUser tokenUser) {

        AttendPlanDO attendPlanDO = attendPlanAddDTO.to(AttendPlanDO.class);
        // 保存
        attendPlanDO = save(attendPlanDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return attendPlanDO.to(AttendPlanVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(AttendPlanUpdateDTO attendPlanUpdateDTO, TokenUser tokenUser) {
        //转DO
        AttendPlanDO attendPlanDO = attendPlanUpdateDTO.to(AttendPlanDO.class);
        //根据主键更新，只更新非null值
        return updateByIdSelective(attendPlanDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... attendPlanIds) {
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) attendPlanIds);
    }


    @Override
    public AttendPlanVO selectById(String attendPlanId, String siteId) {
        AttendPlanDO attendPlanDO = selectDOById(attendPlanId, siteId);
        if (attendPlanDO == null) {
            return null;
        }
        return attendPlanDO.to(AttendPlanVO.class);
    }

    @Override
    public List<AttendPlanListVO> select(AttendPlanQuery attendPlanQuery, String siteId) {
        List<AttendPlanDO> attendPlanDOList = selectDO(attendPlanQuery, siteId);
        if(CollectionUtils.isEmpty(attendPlanDOList)) {
            return attendPlanDOList == null ? null : new ArrayList<>();
        }
        return attendPlanDOList.stream()
                .map(attendPlanDO -> attendPlanDO.to(AttendPlanListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(AttendPlanQuery attendPlanQuery, String siteId) {
        Example example = buildExample(attendPlanQuery,siteId);
        return attendPlanDAO.selectCountByExample(example);
    }

    @Override
    public Page<AttendPlanListVO> selectPage(AttendPlanQuery attendPlanQuery, String siteId) {

        Example example = buildExample(attendPlanQuery,siteId);
        Page<AttendPlanDO> page = attendPlanDAO.selectPageByExample(example,
                attendPlanQuery.getPageNo(),
                attendPlanQuery.getPageSize());

        return page.to(AttendPlanListVO.class);
    }

    @Override
    public AttendPlanDO selectDOById(String attendPlanId, String siteId) {
        return listById(attendPlanId, siteId);
    }

    @Override
    public AttendPlanDO selectDOById(String attendPlanId) {
        return attendPlanDAO.selectByPrimaryKey(attendPlanId);
    }

    @Override
    public AttendPlanDO selectByIdIgnoreValid(String attendPlanId) {
        Example example = new Example(AttendPlanDO.class);
        example.and().andEqualTo("id",attendPlanId);
        return attendPlanDAO.selectOneByExample(example);
    }

    @Override
    public List<AttendPlanDO> selectDO(AttendPlanQuery attendPlanQuery, String siteId) {
        Example example = buildExample(attendPlanQuery,siteId);
        return attendPlanDAO.selectByExample(example);
    }

    @Override
    public List<AttendPlanDO> selectDOByisSynchLegalHoliday(Boolean isSynchLegalHoliday) {
        Example example = new Example(AttendPlanDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("isSynchLegalHoliday", isSynchLegalHoliday);
        return attendPlanDAO.selectByExample(example);
    }

    /**
     * 查询当前用户使用的考勤规则
     *
     * @param empInfoId
     * @param attendDateStr
     * @param siteId
     * @return
     */
    @Override
    public List<AttendPlanDO> getAttendPlan(String empInfoId, String attendDateStr, String siteId) {

        List<String> attendPlanIds = new ArrayList<>();

        // 查询当前用户使用的考勤规则
        AttendPunchStaffQuery attendPunchStaffQuery = new AttendPunchStaffQuery();
        attendPunchStaffQuery.setEmpInfoId(empInfoId);
        List<AttendPunchStaffDO> attendPunchStaffDOList = attendPunchStaffService.selectDO(attendPunchStaffQuery, siteId);

        // 如果打卡人员中没有，则查询员工的打卡部门
        if (attendPunchStaffDOList.size() <= 0) {

            // 查询员工所在部门
            EmpDepQuery empDepQuery = new EmpDepQuery();
            empDepQuery.setEmpId(empInfoId);
            List<EmpDepDO> empDepList = empDepService.selectDO(empDepQuery, siteId);
            if (empDepList.size() <= 0) {
                return null;
            }

            List<String> depIds = new ArrayList<>();
            for (EmpDepDO empDep : empDepList) {
                depIds.add(empDep.getDepId());
            }

            // 查询打卡部门
            AttendPunchDeptQuery attendPunchDeptQuery = new AttendPunchDeptQuery();
            attendPunchDeptQuery.setDeptIds(depIds);
            List<AttendPunchDeptDO> attendPunchDeptList = attendPunchDeptService.selectDO(attendPunchDeptQuery, siteId);
            if (attendPunchDeptList.size() <= 0) {
                return null;
            }

            for (AttendPunchDeptDO attendPunchDept : attendPunchDeptList) {
                attendPlanIds.add(attendPunchDept.getAttendPlanId());
            }
        }
        // 过滤打卡人员使用的考勤规则
        else {

            for (AttendPunchStaffDO attendPunchStaff : attendPunchStaffDOList) {
                attendPlanIds.add(attendPunchStaff.getAttendPlanId());
            }
        }

        // 查询考勤排班的员工使用的考勤规则 (考勤人员排班表)
        AttendShiftStaffScheduleQuery attendShiftStaffScheduleQuery = new AttendShiftStaffScheduleQuery();
        attendShiftStaffScheduleQuery.setEmpInfoId(empInfoId);
        attendShiftStaffScheduleQuery.setYearly(attendDateStr.split("-")[0]);
        attendShiftStaffScheduleQuery.setMonthly(attendDateStr.split("-")[1]);
        attendShiftStaffScheduleQuery.setDaily(attendDateStr.split("-")[2]);
        List<AttendShiftStaffScheduleDO> attendShiftStaffScheduleList = attendShiftStaffScheduleService.selectDO(attendShiftStaffScheduleQuery, siteId);
        if (attendShiftStaffScheduleList.size() > 0) {
            for (AttendShiftStaffScheduleDO attendShiftStaffSchedule : attendShiftStaffScheduleList) {
                attendPlanIds.add(attendShiftStaffSchedule.getAttendPlanId());
            }
        }

        if (attendPlanIds.size() <= 0) {
            return null;
        }

        AttendPlanQuery attendPlanQuery = new AttendPlanQuery();
        attendPlanQuery.setIds(attendPlanIds);
        List<AttendPlanDO> attendPlanList = this.selectDO(attendPlanQuery, siteId);
        if (attendPlanList.size() <= 0) {
            return null;
        }

        log.info("查询当前用户使用的考勤规则：" + JSON.toJSONString(attendPlanList));

        return attendPlanList;
    }

    /**
     * 根据查询参数，构建example

     * @param attendPlanQuery 查询参数
     * @param siteId 所属站点id
     * @return example
     */
    private Example buildExample(AttendPlanQuery attendPlanQuery, String siteId) {
        Example example = new Example(AttendPlanDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (attendPlanQuery.getIds() != null && attendPlanQuery.getIds().size() > 0) {
            example.and().andIn("id", attendPlanQuery.getIds());
        }
        if (attendPlanQuery.getCompanyId() != null) {
            example.and().andLike("companyId", "%" + attendPlanQuery.getCompanyId() + "%");
        }
        if (attendPlanQuery.getCompanyName() != null) {
            example.and().andLike("companyName", "%" + attendPlanQuery.getCompanyName() + "%");
        }
        if (attendPlanQuery.getName() != null) {
//            example.and().andLike("name", "%" + attendPlanQuery.getName() + "%");
            example.and().andEqualTo("name", attendPlanQuery.getName());
        }
        if (attendPlanQuery.getPlanType() != null) {
            example.and().andEqualTo("planType", attendPlanQuery.getPlanType());
        }
        if (attendPlanQuery.getPunchLocationJson() != null) {
            example.and().andLike("punchLocationJson", "%" + attendPlanQuery.getPunchLocationJson() + "%");
        }
        if (attendPlanQuery.getPunchWifiJson() != null) {
            example.and().andLike("punchWifiJson", "%" + attendPlanQuery.getPunchWifiJson() + "%");
        }
        if (attendPlanQuery.getOvertimeRule() != null) {
            example.and().andEqualTo("overtimeRule", attendPlanQuery.getOvertimeRule());
        }
        if (attendPlanQuery.getIsSynchLegalHoliday() != null) {
            example.and().andEqualTo("isSynchLegalHoliday", attendPlanQuery.getIsSynchLegalHoliday());
        }
        if (attendPlanQuery.getIsRemind() != null) {
            example.and().andEqualTo("isRemind", attendPlanQuery.getIsRemind());
        }
        if (attendPlanQuery.getRemindBefore() != null) {
            example.and().andEqualTo("remindBefore", attendPlanQuery.getRemindBefore());
        }
        if (attendPlanQuery.getRemindAfter() != null) {
            example.and().andEqualTo("remindAfter", attendPlanQuery.getRemindAfter());
        }
        if (attendPlanQuery.getIsTakePhoto() != null) {
            example.and().andEqualTo("isTakePhoto", attendPlanQuery.getIsTakePhoto());
        }
        if (attendPlanQuery.getIsOnlyPhoto() != null) {
            example.and().andEqualTo("isOnlyPhoto", attendPlanQuery.getIsOnlyPhoto());
        }
        if (attendPlanQuery.getPunchRange() != null) {
            example.and().andEqualTo("punchRange", attendPlanQuery.getPunchRange());
        }
        if (attendPlanQuery.getIsMakeUp() != null) {
            example.and().andEqualTo("isMakeUp", attendPlanQuery.getIsMakeUp());
        }
        if (attendPlanQuery.getMaxMakeUpCounts() != null) {
            example.and().andEqualTo("maxMakeUpCounts", attendPlanQuery.getMaxMakeUpCounts());
        }
        if (attendPlanQuery.getTakeEffect() != null) {
            example.and().andEqualTo("takeEffect", attendPlanQuery.getTakeEffect());
        }
        if (attendPlanQuery.getStartEffectTime() != null) {
            example.and().andEqualTo("startEffectTime", attendPlanQuery.getStartEffectTime());
        }
        if (attendPlanQuery.getGmtCreateStart() != null &&
                attendPlanQuery.getGmtCreateEnd() != null) {
            example.and().andBetween("gmtCreate", attendPlanQuery.getGmtCreateStart(),
                    attendPlanQuery.getGmtCreateEnd());
        }
        if (attendPlanQuery.getCreateUserId() != null) {
            example.and().andLike("createUserId", "%" + attendPlanQuery.getCreateUserId() + "%");
        }
        if (attendPlanQuery.getGmtModifiedStart() != null &&
                attendPlanQuery.getGmtModifiedEnd() != null) {
            example.and().andBetween("gmtModified", attendPlanQuery.getGmtModifiedStart(),
                    attendPlanQuery.getGmtModifiedEnd());
        }
        if (attendPlanQuery.getModifiedUserId() != null) {
            example.and().andLike("modifiedUserId", "%" + attendPlanQuery.getModifiedUserId() + "%");
        }
        // 排序
        ExampleKit.setExampleOrder(example,attendPlanQuery.getOrders());
        return example;
    }
}




